#pragma once 

#include "threadpool.h"
#include <functional>
#include <iostream>
namespace TinyRPC{

ThreadPool::ThreadPool(int numThreads)
: m_numThreads(numThreads)
, m_quit(false)
{
    for(int i=0;i<m_numThreads;i++){
        m_threads.emplace_back(new Thread(std::bind(&ThreadPool::threadFunc, this)));
    }
    for(int i=0;i<m_numThreads;i++){
        m_threads[i]->start();
    }
}
void ThreadPool::push(const Task& t){
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_taskQueue.push_back(t);
    }
    m_notEmptyCondition.notify_one();
    
}

void ThreadPool::push(Task&& t){
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_taskQueue.push_back(std::move(t));
    }
    m_notEmptyCondition.notify_one();
    
}

void ThreadPool::threadFunc(){
    while (!m_quit)
    {
        Task task = Task::EmptyTask();
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            /*
                唤醒有两种可能
                1 用户调用quit(), 并且唤醒所有可能阻塞的线程
                2 添加任务, 并且唤醒所有可能阻塞的线性
            */
            while (!m_quit && m_taskQueue.empty())
            {
                m_notEmptyCondition.wait(lock);
            }

            if(!m_quit){
                task = std::move(m_taskQueue.front());
                m_taskQueue.pop_front();
            }
            
        }
        if(!m_quit) {
            task.run();
        }else{
            break;
        }
        
    }
    
}

void ThreadPool::quit(){
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_quit = true;
        m_notEmptyCondition.notify_all();
    }
    
    // 等到线程退出
    for(int i=0;i<m_threads.size();i++){
        m_threads[i]->join();
    }
}


}